package com.jz.netthings.appengine.queue;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.github.tobato.fastdfs.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.jz.netthings.appengine.baseData.ProviderData;
import com.jz.netthings.appengine.baseData.ProviderInfo;
import com.jz.netthings.appengine.config.FastProperties;
import com.jz.netthings.appengine.mapper.ProviderDataMapper;
import com.jz.netthings.appengine.mapper.ProviderInfoMapper;
import com.jz.netthings.exception.AdscmSystemException;
import com.jz.netthings.utils.AdscmBaseUtils;
import com.jz.netthings.utils.AdscmDateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 浆员营运流程的缓存
 */
@Service("providerQueue")
public class ProviderQueue{

    /**
     * 所有状态
     */
    public static final int REGISTER = 1;//已经登记，等待体检
    public static final int BODYCALL = 2;//体检中
    public static final int BODYPASS = 3;//体检完成，等待化检/等待采浆
    public static final int ASSAYCALL = 4;//化检中
    public static final int ASSAYPASS = 5;//化检完成，等待采浆
    public static final int ALLOTPASS = 6;//已经叫号分配，采浆中
    public static final int COLLECTSTART = 7;//开始采浆，采浆中
    public static final int COLLECTFINISH = 8;//采浆完成

    Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private ProviderDataMapper providerDataMapper;
    @Autowired
    private ProviderInfoMapper providerInfoMapper;
    @Autowired
    FastFileStorageClient storageClient;
    @Autowired
    FastProperties fastProperties;

    /**
     * 浆员登记，自动生成登记号，并存储当天浆员献浆的全流程数据
     * （登记的时候，就存储 needAssay 是否需要采浆前化检字段 ， needXp 是否需要重新拍胸片字段）
     * @param providerData
     * @return
     */
    public ProviderData providerRegister(ProviderData providerData){

        ProviderData provider = null;
        if(providerData != null){
            if (providerData.getProviderId() >= 0){
                provider = providerDataMapper.selectById(providerData.getProviderId());

                if (provider == null){
                    //证明还没登记
                    logger.info("浆员【"+ providerData.getName() +"】开始登记，并存储当天浆员献浆的全流程数据...");
                    Integer maxRegisterIdx = providerDataMapper.getMaxRegisterIdx();
                    if (maxRegisterIdx == null){
                        maxRegisterIdx = 0;
                    }
                    maxRegisterIdx += 1;

                    Date now = new Date();
                    String prefix = AdscmDateUtils.getNowOnlyDateFomat2(now);

                    String str = AdscmBaseUtils.getInstance().addZeroToStr(maxRegisterIdx + "", 4, "0");

                    //登记信息
                    providerData.setRegisterIdx(maxRegisterIdx);
                    providerData.setRegisterNo(prefix + str);
                    providerData.setRegisterTime(now);

                    //当前状态
                    providerData.setCurrentStatus(ProviderQueue.REGISTER);

                    //获取头像
                    byte[] photo = null;
                    try{
                        ProviderInfo providerInfo = providerInfoMapper.selectById(providerData.getProviderId());

                        String baseUrl = fastProperties.getBaseUrl();

                        photo = storageClient.downloadFile("group1", baseUrl + providerInfo.getPhoto(), new DownloadByteArray());

                    }catch (Exception e){
                        photo = AdscmBaseUtils.getInstance().getNullProviderPhoto();
                        logger.error("从FastDFS 文件系统下载浆员建档照片失败...",e);
                    }
                    providerData.setPhoto(photo);

                    providerDataMapper.insert(providerData);

                    provider = providerData;
                }
            }
        }
        return provider;
    }


    /**
     * 根据状态，获取指定状态的浆员流程数据集合
     * @param statusList
     * @return
     */
    public List<ProviderData> getProviderListByStatus(List<Integer> statusList) throws AdscmSystemException {
        List<ProviderData> list = null;
        try{
            if (statusList != null && statusList.size() > 0){
                logger.info("根据浆员当前的状态【"+statusList+"】，获取此状态下的浆员献浆的全流程数据...");

                list = providerDataMapper.selectListByStatus(statusList,null,null);

            }
        }catch (Exception e){
            String msg = "根据浆员当前的状态【"+statusList+"】，获取此状态下的浆员献浆的全流程数据异常";
            logger.error(msg,e);
            throw new AdscmSystemException(msg);
        }

        return list;
    }
    /**
     * 根据指令，获取指定状态的浆员流程数据集合
     * @param doCmd
     * @return
     */
    public List<ProviderData> getProviderListByCmd(String doCmd) throws AdscmSystemException {
        List<ProviderData> list = null;
        try{

            logger.info("获取指令【"+doCmd+"】状态下的浆员献浆的全流程数据...");

            List<Integer> statusList = new ArrayList<>();
            String condition = null;
            String order = null;

            switch (doCmd) {
                case "WaitBodyCallList":
                    //等待体检
                    statusList.add(REGISTER);
                    order = " ORDER BY registerTime ";
                    break;
                case "WaitBodyPassList":
                    //体检中
                    statusList.add(BODYCALL);
                    order = " ORDER BY bodyCheckCallTime ";
                    break;
                case "WaitAssayCallList":
                    //等待化检
                    statusList.add(BODYPASS);
                    condition = " needAssay = 1 ";
                    order = " ORDER BY bodyCheckPassTime ";
                    break;
                case "WaitAssayPassList":
                    //化检中
                    statusList.add(ASSAYCALL);
                    order = " ORDER BY assayCallTime ";
                    break;
                case "WaitCollectingList":
                    //等待采浆
//                    statusList.add(BODYPASS);
//                    statusList.add(ASSAYPASS);
                    condition = "  ( currentStatus = 3 AND ( needAssay IS NULL OR needAssay = 0 ))" +
                            " OR  ( currentStatus = 5 AND ( needAssay = 1 ))";

                    order = " ORDER BY bodyCheckPassTime,assayPassTime ";

                    break;
                case "CollectingList":
                    //采浆中
                    statusList.add(ALLOTPASS);
                    statusList.add(COLLECTSTART);
                    order = " ORDER BY allotTime ";
                    break;
                case "FinishCollectList":
                    //采浆完成
                    statusList.add(COLLECTFINISH);
                    order = " ORDER BY collectFinishTime ";
                    break;
                default:
                    break;
            }

                list = providerDataMapper.selectListByStatus(statusList,condition,order);

        }catch (Exception e){
            String msg = "获取指令【"+doCmd+"】状态下的浆员献浆的全流程数据异常";
            logger.error(msg,e);
            throw new AdscmSystemException(msg);
        }

        return list;
    }

    /**
     * 更新浆员的全流程数据
     * @param providerData
     * @return
     */
    public ProviderData updateProviderData(ProviderData providerData){
        logger.info("更新浆员的全流程数据...");

        int status = ProviderQueue.REGISTER;

        if (providerData.getCollectFinishTime() != null){
            //采浆完成
            status = ProviderQueue.COLLECTFINISH;
        }else if (providerData.getCollectStartTime() != null){
            //开始采浆，采浆中
            status = ProviderQueue.COLLECTSTART;
        }else if (providerData.getAllotTime() != null){
            //已经叫号分配，采浆中
            status = ProviderQueue.ALLOTPASS;
        }else if (providerData.getAssayPassTime() != null){
            //化检完成，等待采浆
            status = ProviderQueue.ASSAYPASS;
        }else if (providerData.getAssayCallTime() != null){
            //化检中
            status = ProviderQueue.ASSAYCALL;
        }else if (providerData.getBodyCheckPassTime() != null){
            //体检完成，等待化检/等待采浆
            status = ProviderQueue.BODYPASS;
        }else if (providerData.getBodyCheckCallTime() != null){
            //体检中
            status = ProviderQueue.BODYCALL;
        }
        providerData.setCurrentStatus(status);

        providerDataMapper.updateById(providerData);

        return providerData;
    }

    /**
     * 查询指定浆员的全流程数据，可以根据参数：providerId，providerNo，idNo，registerNo
     * @param providerData
     * @return
     */
    public ProviderData selectProviderData(ProviderData providerData) throws AdscmSystemException {

        try{
            logger.info("查询指定浆员的全流程数据...");

            Wrapper<ProviderData> wrapper = new EntityWrapper<>();

            if (providerData.getProviderId() > 0){
                wrapper.eq("providerId",providerData.getProviderId());
            }else  if(providerData.getProviderNo()  != null && !"".equals(providerData.getProviderNo())){
                wrapper.eq("providerNo",providerData.getProviderNo());
            }else  if(providerData.getIdNo()  != null && !"".equals(providerData.getIdNo())){
                wrapper.eq("idNo",providerData.getIdNo());
            }else  if(providerData.getRegisterNo()  != null && !"".equals(providerData.getRegisterNo())){
                wrapper.eq("registerNo",providerData.getRegisterNo());
            }
            List<ProviderData> list = providerDataMapper.selectList(wrapper);

            if (list != null && list.size()>0){
                providerData = list.get(0);
            }
        }catch (Exception e){
            String msg = "查询指定浆员的全流程数据异常";
            logger.error(msg,e);
            throw new AdscmSystemException(msg);
        }

        return providerData;
    }


    /**
     * 清除所有数据，供定时器调用，清除当天所有的流程数据
     */
    public void cleanAll(){
        providerDataMapper.delete(null);
    }

    /**
     * 根据卡号，获取浆员
     * @param providerNo
     * @return
     */
    public ProviderData getByProviderNo(String providerNo){

        ProviderData data = null;
        Wrapper<ProviderData> wrapper = new EntityWrapper<>();
        wrapper.eq("providerNo",providerNo);

        List<ProviderData> dataList = providerDataMapper.selectList(wrapper);

        if (dataList != null && dataList.size()>0){
            data = dataList.get(0);
        }
        return data;
    }
}
